<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue3中的响应式原理</title>
</head>
<body>

<script type="text/javascript">
    // 源数据
    let person = {
        name: '张三',
        age: 18
    }

    // // 1、模拟Vue2中实现响应式【无法捕获到新增的对象属性，只能捕获到对对象属性的读取和修改】，所以vue2使用这个方式实现响应式有一点缺陷。
    // let p = {};
    // Object.defineProperty(p, 'name', {
    //     configurable: true, // 允许删除对象的属性
    //     get: function () { // 有人读取 name 的时候调用
    //         return person.name;
    //     },
    //     set: function (value) {
    //         console.log('有人修改了 name 属性，我发现了，我要去更新界面');
    //         person.name = value;
    //     }
    // });
    // Object.defineProperty(p, 'age', {
    //     get: function () { // 有人读取 age 的时候调用
    //         return person.age;
    //     },
    //     set: function (value) {
    //         console.log('有人修改了 age 属性，我发现了，我要去更新界面');
    //         person.age = value;
    //     }
    // });

    // // 2、模拟Vue3中实现响应式。window.Proxy，其中window自带Proxy
    // const p = new Proxy(person, {
    //     // 【读取】有人读取p的某个属性的时候调用
    //     get(target, propName) {
    //         console.log(`有人读取了person的${propName}属性`, propName);
    //         return target[propName];
    //     },
    //     // 【修改、新增】有人修改p的某个属性，或者给p追加某个属性的时候调用
    //     set(target, propName, newValue) {
    //         console.log(`有人修改了person的${propName}属性，我要去更新界面了！`, target, propName, newValue);
    //         target[propName] = newValue;
    //     },
    //     // 【删除】有人读取了p的某个属性的时候调用
    //     delete(target, propName) {
    //         console.log(`有人删除了person的${propName}属性，我要去更新界面了！`, target, propName, newValue);
    //         return delete target[propName];
    //     },
    // });


    // window.Reflect反射，其中window身上自带Reflect
    // 3、模拟Vue3中实现响应式，Reflect写法
    // #region
    // 其中Person是源对象，p是代理对象
    const p = new Proxy(person, {
        // 查询：有人读取p的某个属性时调用
        get(target, propName) {
            console.log(`有人读取了p身上的${propName}属性`)
            return Reflect.get(target, propName)
        },
        // 新增或修改：有人修改p的某个属性、或给p追加某个属性时调用
        set(target, propName, value) {
            console.log(`有人修改了p身上的${propName}属性，我要去更新界面了！`)
            Reflect.set(target, propName, value)
        },
        // 删除：有人删除p的某个属性时调用
        deleteProperty(target, propName) {
            console.log(`有人删除了p身上的${propName}属性，我要去更新界面了！`)
            return Reflect.deleteProperty(target, propName)
        }
    })
    // #endregion

    // // 4、通过Object.defineProperty 去操作
    // let obj = {a: 1, b: 2}
    // // #region
    // try {
    //     Object.defineProperty(obj, 'c', {
    //         get() {
    //             return 3
    //         }
    //     })
    //     Object.defineProperty(obj, 'c', {
    //         get() {
    //             return 4
    //         }
    //     })
    // } catch (error) {
    //     console.log(error)
    // }
    // // #endregion
    //
    // // 5、通过 Reflect.defineProperty去操作，通过Reflect 可以减少try、catch的语句
    // // #region
    // const x1 = Reflect.defineProperty(obj, 'c', {
    //     get() {
    //         return 3
    //     }
    // })
    // console.log(x1)
    //
    // const x2 = Reflect.defineProperty(obj, 'c', {
    //     get() {
    //         return 4
    //     }
    // })
    // if (x2) {
    //     console.log('某某某操作成功了！')
    // } else {
    //     console.log('某某某操作失败了！')
    // }
    // // #endregion
    // console.log('@@@')


</script>

</body>
</html>